using System;
using System.Linq;
using System.Web.Mvc;
using OurWedding1.IO;
using OurWedding1.Models;
using OurWedding1.Mailers;
using System.IO;


namespace OurWedding1.Controllers
{
    [Authorize]
    public class ConfirmationKeysController : BaseController
    {
        private IUserMailer _userMailer = new UserMailer();
        public IUserMailer UserMailer
        {
            get { return _userMailer; }
            set { _userMailer = value; }
        }
        private readonly IGuestGroupRepository _guestgroupRepository;
        private readonly IConfirmationKeyRepository _confirmationkeyRepository;
        private readonly IGuestRepository _guestRepository;
        private readonly IWeddingRepository _weddingRepository;

        // If you are using Dependency Injection, you can delete the following constructor
        public ConfirmationKeysController()
            : this(new GuestGroupRepository(), new ConfirmationKeyRepository(), new GuestRepository())
        {

        }

        public ConfirmationKeysController(IGuestGroupRepository guestgroupRepository, IConfirmationKeyRepository confirmationkeyRepository, IGuestRepository guestRepository)
        {
            _guestgroupRepository = guestgroupRepository;
            _confirmationkeyRepository = confirmationkeyRepository;
            _guestRepository = guestRepository;
            _weddingRepository = new WeddingRepository();
        }

        //
        // GET: /ConfirmationKeys/

        public ActionResult Index()
        {
            var selectedWedding = SelectedWeddingId;
            if (!selectedWedding.HasValue)
            {
                return RedirectToAction("Index", "Weddings");
            }
            var model = _confirmationkeyRepository.AllIncluding(confirmationkey => confirmationkey.GuestGroup);
            model = model.Where(d => d.GuestGroup.WeddingId == selectedWedding.Value);
            return View(model);
        }

        //
        // GET: /ConfirmationKeys/

        public ActionResult IndexAjax()
        {
            var selectedWedding = SelectedWeddingId;
            if (!selectedWedding.HasValue)
            {
                return RedirectToAction("Index", "Weddings");
            }
            var model = _confirmationkeyRepository.AllIncluding(confirmationkey => confirmationkey.GuestGroup);
            model = model.Where(d => d.GuestGroup.WeddingId == selectedWedding.Value);
            return PartialView("_Index", model);
        }

        //
        // GET: /ConfirmationKeys/Details/5

        public ViewResult Details(int id)
        {
            var model = _confirmationkeyRepository.Find(id);
            return View(model);
        }

        //
        // GET: /ConfirmationKeys/Create



        [AllowAnonymous]
        public ActionResult Confirm(string key)
        {
            var model = _confirmationkeyRepository.All.SingleOrDefault(c => c.Key == key);
            if (model == null)
            {
                return View("NotFound");
            }

            return View(model);
        }

        [AllowAnonymous]
        [HttpPost, ActionName("Confirm")]
        public ActionResult ConfirmConfirmed(string key)
        {
            var model = _confirmationkeyRepository.All.SingleOrDefault(c => c.Key == key);
            if (model == null)
            {
                return View("NotFound");
            }

            var guests = _guestRepository.All.Where(g => g.GuestGroupId == model.GuestGroupId).ToList();

            guests.ForEach(a => a.isConfirmed = true);
            _guestRepository.Save();

            model.isConfirmed = true;
            model.ConfirmationDate = DateTime.Now;
            _confirmationkeyRepository.Save();

            var users = UsersInWeddingRepository.All.Where(d => d.WeddingId == model.GuestGroup.WeddingId).Select(d => d.UserProfile).ToList();

            UserMailer.Confirmed(model.GuestGroup, users).Send();
            var wedding = _weddingRepository.Find(model.GuestGroup.WeddingId);
            if (wedding.Date != null)
            {
                TimeSpan remaining = wedding.Date.Value.Subtract(DateTime.Now);
                ViewBag.Days = remaining.Days;
            }
            ViewBag.Date = wedding.Date;
            return View("ConfirmConfirmed", model);
        }

        public ActionResult Create()
        {
            ViewBag.PossibleGuestGroups = _guestgroupRepository.All;
            var model = new ConfirmationKey
                {
                    Key = ConfirmationKey.GeneratePassword(10, 0),
                    isReleased = false,
                    isConfirmed = false
                };
            return View(model);
        }

        //
        // POST: /ConfirmationKeys/Create

        [HttpPost]
        public ActionResult Create(ConfirmationKey confirmationkey)
        {
            if (ModelState.IsValid)
            {
                _confirmationkeyRepository.InsertOrUpdate(confirmationkey);
                _confirmationkeyRepository.Save();
                return RedirectToAction("Index");
            }
            ViewBag.PossibleGuestGroups = _guestgroupRepository.All;
            return View();
        }

        //GET: /ConfirmationKeys/GenerateForWedding/1
        public ActionResult Generate()
        {
            var selectedWedding = SelectedWeddingId;
            if (!selectedWedding.HasValue)
            {
                return Content("");
            }
            var wedding = _weddingRepository.Find(selectedWedding.Value);
            if (wedding == null)
            {
                return Content("");
            }
            var existedRspvs = _confirmationkeyRepository.All.Where(d => d.GuestGroup.WeddingId == wedding.WeddingId).Select(g => g.GuestGroupId).ToList();
            var existed = _confirmationkeyRepository.All.ToDictionary(d => d.Key);
            var guestGroups = _guestgroupRepository.All.Where(g => g.WeddingId == wedding.WeddingId).ToList();
            int amount = 0;
            foreach (var item in guestGroups)
            {
                if (!existedRspvs.Contains(item.GuestGroupId))
                {
                    ConfirmationKey candidate;
                    do
                    {
                        candidate = new ConfirmationKey(item);
                    } while (existed.ContainsKey(candidate.Key));

                    _confirmationkeyRepository.InsertOrUpdate(candidate);
                    existed.Add(candidate.Key, candidate);
                    amount++;
                }
            }
            bool succeded;
            try
            {
                _confirmationkeyRepository.Save();
                succeded = true;
            }
            catch (Exception)
            {
                succeded = false;
            }
            if (succeded)
            {
                return Json(new
                {
                    value = amount
                }, JsonRequestBehavior.AllowGet);
            }
            return Content("");
        }

        public ActionResult DeleteNotReleased()
        {
            var selectedWedding = SelectedWeddingId;
            if (!selectedWedding.HasValue)
            {
                return Content("");
            }
            var wedding = _weddingRepository.Find(selectedWedding.Value);
            if (wedding == null)
            {
                return Content("");
            }
            var existedRspvs = _confirmationkeyRepository.All.Where(d => d.GuestGroup.WeddingId == wedding.WeddingId).Where(r => !r.isReleased).ToList();
            int amount = 0; bool succeded;
            foreach (var item in existedRspvs)
            {
                _confirmationkeyRepository.Delete(item.ConfirmationKeyId);
                amount++;
            }
            try
            {
                _confirmationkeyRepository.Save();
                succeded = true;
            }
            catch (Exception)
            {
                succeded = false;
            }
            if (succeded)
            {
                return Json(new
                {
                    value = amount
                }, JsonRequestBehavior.AllowGet);
            }
            return Content("");
        }


        public ActionResult RenderPdf(int id, int? fontFamily)
        {
            var model = _confirmationkeyRepository.Find(id); //TODO:Security!
            FontStyle style;
            switch (fontFamily)
            {
                case 0:
                    style = FontStyle.ItaliannoRegular;
                    break;
                case 1:
                    style = FontStyle.GrandHotelRegular;
                    break;
                default:
                    style = FontStyle.ItaliannoRegular;
                    break;
            }
            var input = new ConfirmationCard
                {
                    ConfirmationText = Resources.Confirm_ConfirmationText,
                    // ReSharper disable PossibleNullReferenceException
                    QrCodeUrl = Url.Action("Confirm", "ConfirmationKeys", new { key = model.Key }, Request.Url.Scheme),
                    // ReSharper restore PossibleNullReferenceException
                    Key = model.Key,
                    FontStyle = style

                };
            var memoryStream = new MemoryStream();
            input.Render(memoryStream);
            return File(memoryStream.GetBuffer(), "application/pdf");
        }

        public ActionResult RenderPdfList(int? fontFamily)
        {
            var selectedWedding = SelectedWeddingId;
            if (!selectedWedding.HasValue)
            {
                return RedirectToAction("Index", "Weddings");
            }
            var keys = _confirmationkeyRepository.AllIncluding(confirmationkey => confirmationkey.GuestGroup).Where(d => d.GuestGroup.WeddingId == selectedWedding.Value).ToList();
            
            FontStyle style;
            switch (fontFamily)
            {
                case 0:
                    style = FontStyle.ItaliannoRegular;
                    break;
                case 1:
                    style = FontStyle.GrandHotelRegular;
                    break;
                default:
                    style = FontStyle.ItaliannoRegular;
                    break;
            }

            var confText = Resources.Confirm_ConfirmationText;

            var model = new TableRenderer();

            foreach (var item in keys)
            {
                model.Rows.Add(new SingleCellTable {Text = item.GuestGroup.Name});
                var row = new ConfirmationCard
                {
                    ConfirmationText = confText,
                    // ReSharper disable PossibleNullReferenceException
                    QrCodeUrl = Url.Action("Confirm", "ConfirmationKeys", new { key = item.Key }, Request.Url.Scheme),
                    // ReSharper restore PossibleNullReferenceException
                    Key = item.Key,
                    FontStyle = style
                };
                model.Rows.Add(row);
            }

            
            var memoryStream = new MemoryStream();
            model.Render(memoryStream);
            return File(memoryStream.GetBuffer(), "application/pdf");
        }


        //
        // GET: /ConfirmationKeys/Edit/5

        public ActionResult Edit(int id)
        {
            ViewBag.PossibleGuestGroups = _guestgroupRepository.All;
            return View(_confirmationkeyRepository.Find(id));
        }

        //
        // POST: /ConfirmationKeys/Edit/5

        [HttpPost]
        public ActionResult Edit(ConfirmationKey confirmationkey)
        {
            if (ModelState.IsValid)
            {
                _confirmationkeyRepository.InsertOrUpdate(confirmationkey);
                _confirmationkeyRepository.Save();
                return RedirectToAction("Index");
            }
            ViewBag.PossibleGuestGroups = _guestgroupRepository.All;
            return View();
        }

        //
        // GET: /ConfirmationKeys/Delete/5

        public ActionResult Delete(int id)
        {
            return View(_confirmationkeyRepository.Find(id));
        }

        //
        // POST: /ConfirmationKeys/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {
            _confirmationkeyRepository.Delete(id);
            _confirmationkeyRepository.Save();

            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _guestgroupRepository.Dispose();
                _confirmationkeyRepository.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

